package novel.spider.impl;

import novel.spider.configuration.Configuration;
import novel.spider.entitys.Chapter;
import novel.spider.entitys.ChapterDetail;
import novel.spider.interfaces.IChapterDetailSpider;
import novel.spider.interfaces.IChapterSpider;
import novel.spider.interfaces.INovelDownload;
import novel.spider.util.ChapterDetailSpiderFactory;
import novel.spider.util.ChapterSpiderrFactory;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
import java.util.concurrent.*;

/**
 * Created by Kau on 2016/10/31.
 */
public class NovelDownload implements INovelDownload {
    @Override
    public String download(String url, Configuration config) {
        IChapterSpider spider = ChapterSpiderrFactory.getChapterSpider(url);
        List<Chapter> chapters = spider.getsChapter(url);
        // 当所有线程下载完毕后，回复主线程下载完成，并合并
        int size = config.getSize();
        // Math.ceil(double) 将double类型转int类型， 10->10 10.5->11 10.1->11 -10 -> -10 -10.5 -> -10
        int maxThreadSize = (int)Math.ceil(chapters.size() * 1.0 / size);
        Map<String, List<Chapter>> downloadTaskAlloc = new HashMap<>();
        for (int i = 0; i < maxThreadSize; i++) {
            int fromIndex = i * (config.getSize());
            int toIndex = i == maxThreadSize - 1 ? chapters.size() - 1 : i * (config.getSize()) + config.getSize() - 1;
            downloadTaskAlloc.put(fromIndex + "-" + toIndex, chapters.subList(fromIndex, toIndex));
        }
        ExecutorService service = Executors.newFixedThreadPool(maxThreadSize);
        Set<String> keySet = downloadTaskAlloc.keySet();
        List<Future<String>> tasks = new ArrayList<>();
        for (String key : keySet){
            tasks.add(service.submit(new DownloadCallable(config.getPath() + "/" + key + ".txt", downloadTaskAlloc.get(key))));
        }
        service.shutdown();
        for (Future<String> future : tasks){
            try {
                System.out.println(future.get() + ",下载完成！");
            } catch (InterruptedException | ExecutionException e){
                e.printStackTrace();
            }
        }
        return null;
    }
}

class DownloadCallable implements Callable<String> {
    private List<Chapter> chapters;
    private String path;

    public DownloadCallable(String path,List<Chapter> chapters) {
        this.chapters = chapters;
        this.path = path;
    }

    @Override
    public String call() throws Exception {
        try (
                PrintWriter out = new PrintWriter(new File(path));
                ) {
            for (Chapter chapter : chapters){
                IChapterDetailSpider spider = ChapterDetailSpiderFactory.getChapterDetailSpider(chapter.getUrl());
                ChapterDetail detail = spider.getChapterDetail(chapter.getUrl());
                out.println(detail.getTitle());
                out.println(detail.getContent());
            }
        } catch (IOException e){
            throw new RuntimeException(e);
        }
        return path;
    }
}